package com.demo2do.fms.admin.web.controller.business;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.page.Page;
import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.demo2do.core.web.resolver.Preloading;
import com.demo2do.core.web.utils.WebUtils;
import com.demo2do.fms.admin.dto.OtherFeeInfo;
import com.demo2do.fms.admin.entity.report.ExportType;
import com.demo2do.fms.admin.entity.report.business.DispatchOrderReportSearch;
import com.demo2do.fms.admin.entity.search.business.DispatchOrderSearch;
import com.demo2do.fms.admin.entity.security.Login;
import com.demo2do.fms.admin.service.business.DispatchOrderService;
import com.demo2do.fms.admin.service.business.ShipmentService;
import com.demo2do.fms.admin.utils.FormatUtils;
import com.demo2do.fms.admin.visitor.impl.PersistentVisitor;
import com.demo2do.fms.admin.web.resolver.Secure;
import com.demo2do.fms.admin.web.view.ExcelTemplateView;
import com.demo2do.fms.entity.business.shipment.DispatchOrder;
import com.demo2do.fms.entity.business.shipment.DispatchOrderRecord;
import com.demo2do.fms.entity.business.shipment.ShipmentOrder;
import com.demo2do.fms.entity.business.shipment.TransportCost;

/**
 * 查询派车单、维护派车单、删除派车单
 * 
 * @author Chang Liu
 *         
 */
@Controller
@RequestMapping("/dispatch-orders")
@MenuSetting("menu-business")
public class DispatchOrderController {
    
    private static final Logger logger = LoggerFactory.getLogger(DispatchOrderController.class);
                                        
    @Autowired
    private DispatchOrderService dispatchOrderService;
                                 
    @Autowired
    private ShipmentService shipmentService;
    
    @Autowired
    private PersistentVisitor persistentVisitor;
                                 
    /**
     * 查询派车单- search panel / 维护派车单 - search panel 
     * 
     * 查询target=search / 维护target=maintain
     * 
     * @param login
     * @param target
     * @param page
     * @return
     */
    @RequestMapping(value = "/search", method = RequestMethod.GET, params = "target")
    @MenuSetting("submenu-dispatch-order-{target}")
    public ModelAndView search(@Secure Login login, @RequestParam(name = "target") String target, Page page) {
        
        ModelAndView modelAndView = new ModelAndView("business/dispatch-order/dispatch-order-search");
        
        modelAndView.addObject("region", login.isRegionUser());
        modelAndView.addObject("orgIds", login.getCurrOrgIds());
        
        modelAndView.addObject("target", target);
        
        return modelAndView;
        
    }
    
    /**
     * 查询派车单-on search / 维护派车单 on search
     * 
     * @param search
     * @param request
     * @param session
     * @param page
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET, params = { "filter", "target" })
    @MenuSetting("submenu-dispatch-order-{target}")
    public ModelAndView onSearch(DispatchOrderSearch search,
                                 HttpServletRequest request, HttpSession session, Page page) {
            
        String target = search.getTarget();
        
        ModelAndView modelAndView = new ModelAndView("business/dispatch-order/dispatch-order-" + target + "-list");
        modelAndView.addObject("target", target);
        
        session.setAttribute("dispatchOrderQueryString", request.getQueryString());
        
        int totals = dispatchOrderService.countDispatch(search);
        if ( totals > 0 ) {
            
            List<DispatchOrder> dispatchOrders = dispatchOrderService.listDispatch(search, page.with(totals));
            
            modelAndView.addObject("dispatchOrders", dispatchOrders);
            modelAndView.addObject("page", page);
            modelAndView.addObject("queryString", WebUtils.extractQueryString(request, "page", "filter", "codeSort", "leavingTimeSort", "dispatchDateSort", "shipmentGroupIdSort", "leavingTime"));
                    
        }
        
        return modelAndView;
        
    }
    
    /**
     * 查询派车单-派车单详情
     * 
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @MenuSetting("submenu-dispatch-order-search")
    public ModelAndView view(@PathVariable("id") Long id) {
        
        ModelAndView modelAndView = new ModelAndView("business/dispatch-order/dispatch-order-view");
        
        // 1. get dispatchOrderRecord by dispatcherId
        DispatchOrderRecord dispatchOrderRecord = dispatchOrderService.loadDispatchOrderRecord(id);
        modelAndView.addObject("dispatchOrderRecord", dispatchOrderRecord);
        
        // 2. get dispatcherOrder by dispatcherId
        DispatchOrder dispatchOrder = dispatchOrderService.loadDispatchOrder(id);
        modelAndView.addObject("dispatchOrder", dispatchOrder);
        
        // 3. get transportCost by dispatcherId
        TransportCost transportCost = dispatchOrderService.getTransportCost(id);
        modelAndView.addObject("transportCost", transportCost);
        
        // 4. get shipment cars by dispatcherId
        List<ShipmentOrder> shipmentOrders = shipmentService.listShipmentOrder(id);
        modelAndView.addObject("shipmentOrders", shipmentOrders);
        
        // 5. get other_fee by dispatch_order
        Map<Long, OtherFeeInfo> otherFeeMap = dispatchOrderService.getOtherFeeMappings(id);
        modelAndView.addObject("otherFeeMap", otherFeeMap);
        
        return modelAndView;
        
    }
    
    /**
     * 维护派车单 - 准备
     * 
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}/prepare", method = RequestMethod.GET, params = "maintain")
    @MenuSetting("submenu-dispatch-order-maintain")
    public ModelAndView maintain(@PathVariable("id") Long id, @RequestParam("maintain") String maintain) {
        
        ModelAndView modelAndView = new ModelAndView("business/dispatch-order/dispatch-order-maintain-prepare");
        
        // 1. get dispatch_order by dispatch_order_id
        DispatchOrder dispatchOrder = dispatchOrderService.loadDispatchOrder(id);
        modelAndView.addObject("dispatchOrder", dispatchOrder);
        
        // 2. get transport_cost by dispatch_order_id
        TransportCost transportCost = dispatchOrderService.getTransportCost(id);
        modelAndView.addObject("transportCost", transportCost);
        
        // 3. get all shipment_orders by dispatch_order
        List<ShipmentOrder> shipmentOrders = shipmentService.listShipmentOrder(id);
        modelAndView.addObject("shipmentOrders", shipmentOrders);
        
        // 4. get other_fee by dispatch_order
        // key - fee_type_id
        // value - other_fee_info
        Map<Long, OtherFeeInfo> otherFeeMap = dispatchOrderService.getOtherFeeMappings(id);
        modelAndView.addObject("otherFeeMap", otherFeeMap);
        
        modelAndView.addObject("maintain", maintain);
        
        return modelAndView;
        
    }
    
    /**
     * 维护派车单 - 准备shipment_order
     * 
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}/prepare-shipment-order", method = RequestMethod.GET, params = "maintain")
    @MenuSetting("submenu-dispatch-order-maintain")
    public ModelAndView maintainShipmentOrder(@PathVariable("id") Long id) {
        
        ModelAndView modelAndView = new ModelAndView("business/dispatch-order/dispatch-order-maintain-prepare-shipment-order");
                
        // get all shipment_orders by dispatch_order
        List<ShipmentOrder> shipmentOrders = shipmentService.listShipmentOrder(id);
        modelAndView.addObject("shipmentOrders", shipmentOrders);
        
        return modelAndView;
    }
    
    /**
     * 维护派车单 - 执行
     * 
     * @param dispatchOrder
     * @param adjustmentDistance
     * @param transportCost
     * @param otherFeeTypeIds
     * @param otherFees
     * @return
     */
    @RequestMapping(value = "/{id}/maintain", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @MenuSetting("submenu-maintenance-dispatch-order")
    public @ResponseBody HttpResult onMaintain(@Preloading("dispatchOrderId") DispatchOrder dispatchOrder,
            @RequestParam("adjustmentDistance") BigDecimal adjustmentDistance, TransportCost transportCost,
            @RequestParam(value = "otherFeeTypeIds") List<Long> otherFeeTypeIds,
            @RequestParam(value = "otherFees", required = false) List<BigDecimal> otherFees,
            @RequestParam(value = "maintain", required = false) String maintain) {
            
        HttpResult httpResult = new HttpResult();
        
        try {
            
            // maintain
            dispatchOrderService.maintain(dispatchOrder, adjustmentDistance, transportCost, otherFeeTypeIds, otherFees);
            
            httpResult.success().message("修改派车单成功");
            
            if(StringUtils.equals("direct", maintain)) {
            	httpResult.data("url", "/dispatch-orders/search?target=maintain");
            }							
            
            
            
        } catch (Exception e) {
            httpResult.fail("500").message("修改派车单失败! " + e.getMessage());
            logger.error("#onMaintain() - maintain dispatch order fail, exception is [{}]", e);
        }
        
        return httpResult;
        
    }
    
    
    /**
     * 
     * @param operator
     * @return
     */
    @RequestMapping(value = "/delete", method = RequestMethod.GET)
    public String disable(@Secure Login operator) {
        return "business/dispatch-order/dispatch-order-delete";
    }
    
    /**
     * 删除派车单 - 执行
     * 
     * @param operator
     * @param dispatchOrderIds
     * @return
     */
    @RequestMapping(value = "/delete", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @MenuSetting("submenu-dispatch-order-maintain")
    public @ResponseBody HttpResult onDisable(@Secure Login operator,
                                              @RequestParam(name = "dispatchOrderIds") List<Long> dispatchOrderIds) {
            
        HttpResult httpResult = new HttpResult();
        
        try {
            
            // 1. define some variables
            int successDeleteNumber = 0; // 成功删除数量
            String errorMessage = ""; // 失败删除派车单信息
            
            // 2. list dispatch_orders by ids
            List<DispatchOrder> dispatchOrders = dispatchOrderService.listDispatchOrder(dispatchOrderIds);
            
            // 3. each dispatch_orders do disable
            for (DispatchOrder dispatchOrder : dispatchOrders) {
                
                // 3.1 已有回单的派车单的派车单不执行删除
                if ( dispatchOrder.hasAccomplishComfirmed() ) {
                    errorMessage = errorMessage + dispatchOrder.getCode() + ",";
                    continue;
                }
                
                // 3.2 删除派车单
                dispatchOrderService.disableDispatchOrder(dispatchOrder, operator);
                
                successDeleteNumber++; // 成功删除数量加1
                
            }
            
            // 删除失败的派车单数
            int failDeleteNumber = dispatchOrderIds.size() - successDeleteNumber;
            
            if ( failDeleteNumber == 0 ) {
                httpResult.success().message("全部取消成功!");
            } else {
                httpResult.fail("")
                        .message("取消成功" + successDeleteNumber + "条，失败" + failDeleteNumber + "条。" + (errorMessage == ""
                                ? "" : ("以下派车单已有回单，不能被取消：" + errorMessage.substring(0, errorMessage.length() - 1))));
            }
            
        } catch (Exception e) {
            logger.error("#onMaintaining() - delete dispatch order fail, exception is [{}]", e);
            httpResult.fail("").message("取消失败！");
        }
        
        return httpResult;
    }
    
    /**
     * 输出当前页记录
     * 
     * @param search
     * @param page
     * @return
     */
    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public ModelAndView export(DispatchOrderSearch search, Page page) {

        ModelAndView modelAndView = new ModelAndView(new ExcelTemplateView("business/dispatch-order-" + search.getTarget() +"-export.xlsx"));
        
        // 1. list dispatch order
        int totals = dispatchOrderService.countDispatch(search);
        if (totals > 0) {
            
            List<DispatchOrder> dispatchOrders = dispatchOrderService.listDispatch(search, page.with(totals));
            modelAndView.addObject("dispatchOrders", dispatchOrders);
                    
        }
        
        // 2. attribute
        modelAndView.addObject("persist", persistentVisitor);
        modelAndView.addObject("type", ExportType.CURRENT);
        
        // 3. format util
        FormatUtils fmt = new FormatUtils();
        modelAndView.addObject("fmt", fmt);
        
        return modelAndView;
        
    }
    
    /**
     * 输出全部记录
     * 
     * @param search
     * @return
     */
    @RequestMapping(value = "/export-all", method = RequestMethod.GET)
    public ModelAndView exportAll(DispatchOrderReportSearch search) {
        
        ModelAndView modelAndView = new ModelAndView(new ExcelTemplateView("business/dispatch-order-" + search.getTarget() +"-export.xlsx"));
        
        // 1. list result 
        List<Map<String, Object>> results = dispatchOrderService.exportAll(search);
        modelAndView.addObject("results", results);
        
        // 2. attribute
        modelAndView.addObject("type", ExportType.ALL);
        
        // 3. format util
        FormatUtils fmt = new FormatUtils();
        modelAndView.addObject("fmt", fmt);
        
        logger.warn("#exportAll() - export size=[{}]...", results.size());
        
        return modelAndView;
        
    }
    
}
